/**
 * GeoSOA/Spatialytics/Featurizer.js
 *
 * Featurizer
 *
 * Copyright (C) 2008-2009 GeoSOA Research Group, Universite Laval
 * See LICENSE file under this distribution for licensing information
 * 
 * @author Etienne Dube
 * @since 20090409
 **/

dojo.provide("GeoSOA.Spatialytics.Featurizer");

dojo.require("GeoSOA.olap4js.Util");

/**
 * Featurizer constructor
 * 
 * A Featurizer is responsible for processing OlapAjax CellSet
 * (resulting from a multidimensional query) in order to produce a GeoJSON
 * FeatureCollection, containing Feature objects (with vector geometries)
 * suitable for drawing on an OpenLayers Vector layer.
 * 
 * The conversion procedure basically works by "flattening" the multidimensional
 * result set (from the CellSet) to a collection of features, having a "value"
 * attribute to which the cell values are affected. For now, this amounts to
 * taking a 1-dimension "slice" of the CellSet, according to the positions
 * ordinal specified by the slicerArray parameter (in the options object).
 * The Featurizer iterates over the positions of the axis specified by
 * geomAxisOrdinal, in order to retrieve the spatial members used to generate
 * Feature objects (using the geometry attribute specified by geomProperty).
 * 
 * @param {Object} options Options passed to the constructor
 *
 * @constructor
 */
GeoSOA.Spatialytics.Featurizer = function (options) {

	var options = options || {};

	// Axis ordinal on which the spatial dimension is to be found
	// (0 = columns, 1 = rows, ...). Defaults to rows (1).
	this.geomAxisOrdinal = options.geomAxisOrdinal || 1;

	// Ordinal of the spatial dimension (hierarchy) in the axis' positions
	// (e.g. 0 if the 1st members of the axis tuples are the spatial members).
	// Defaults to 0.
	this.geomHierarchyOrdinal = options.geomHierarchyOrdinal || 0; 

	// Name of the geometry member property (must be the same across all
	// levels). Defaults to "geom".
	this.geomProperty = options.geomProperty || "geom";

	// Array of positions ordinals on all the axes (except filter)
	// starting from 0 (columns) defining which position ordinals to use for
	// selecting cells (from the CellSet) from which values are to be assigned
	// to spatial features.
	// This effectively acts as a slicer on the result, keeping a 1-dimensional
	// slice of the CellSet, over which we iterate on positions of the remaining
	// axis to retrieve spatial members (and cell values for the spatial
	// features).
	// Specifying a position ordinal for the geometry axis (i.e. the axis
	// ordinal specified by this.geomAxisOrdinal) has no effect (it will be
	// ignored).
	// If no position ordinal is specified for a given axis (e.g. if the array
	// is empty) it defaults to position 0.
	this.slicerArray = options.slicerArray || [0];

};

// member functions

GeoSOA.Spatialytics.Featurizer.prototype.featurize = function (cellSet) {

	var i;

	// prepare the GeoJSON FeatureCollection
	var geojsonFeatColl = {
			features: [],
			type: "FeatureCollection"
	};
	
	if (cellSet != null) {

		var geomCellSetAxis = cellSet.getAxis(this.geomAxisOrdinal);

		// prepare initial coordinates array
		var coordArray = [];
		for (i = 0; i < cellSet.getNumberOfAxes(); i++) {
	
			// is this the geometry axis?
			if (i == this.geomAxisOrdinal) {
				// we start at position 0 on this axis, next loop will
				// iterate over all positions
				coordArray[i] = 0;
			}
			// do we have a specified position ordinal for this axis in
			// the slicerArray?
			else if (this.slicerArray[i] != undefined) {
				coordArray[i] = this.slicerArray[i];
			}
			else {
				// otherwise, defaults to position ordinal 0 for this axis
				coordArray[i] = 0;
			}
	
		}

		// get a "treeified" representation of the geometry axis
		var treeifiedGeomAxis = GeoSOA.olap4js.Util.treeifyAxis(geomCellSetAxis);
	
		// retrieve members and geometry properties of the geometry axis,
		// and cell values from the CellSet (according to the slicerArray)
		for (i = 0; i < geomCellSetAxis.positions.length; i++) {
	
			// retrieve the geometry member and geometry property
			var geomPosition = geomCellSetAxis.positions[i];
			var geomMember = geomPosition.members[this.geomHierarchyOrdinal];
			var geomPropValue = geomMember.properties[this.geomProperty];
	
			// set the coordinates and retrieve the current cell
			coordArray[this.geomAxisOrdinal] = i;
			var cellValue = cellSet.getCell(coordArray);
	
			uid = cellSet.axes[this.geomAxisOrdinal].members[this.geomHierarchyOrdinal][i].properties.MEMBER_UNIQUE_NAME;
	
			// construct the GeoJSON feature
			var geojsonFeat = {
					geometry: geomPropValue,
					id: i,
					properties: {
							memberName: geomMember.name,
							name: geomMember.name,
							children : geomMember.properties.CHILDREN_CARDINALITY,
							parent : geomMember.properties.PARENT_LEVEL,
							value: cellValue,
							// ordinal of the geometry member axis:
							axisOrdinal: this.geomAxisOrdinal,
							// ordinal of the geometry member position
							positionOrdinal: i,
							// ordinal of the geometry member (in the position)
							memberOrdinal: this.geomHierarchyOrdinal,
							uniqueName: uid,
					},
			type: "Feature"
			};
	
			geojsonFeatColl.features.push(geojsonFeat);
		}
	}
		
	return geojsonFeatColl;
};

GeoSOA.Spatialytics.Featurizer.prototype.setSlicer = function (arrayValue) {
	this.slicerArray = [arrayValue];
}
